/**
 * Copyright: Copyright (c)2011
 * Company: 易宝支付(YeePay)
 */
package net.loyintean.pearlshell.validation.rule;

import java.math.BigDecimal;

import net.loyintean.pearlshell.base.util.BigDecimalUtil;
import net.loyintean.pearlshell.validation.IValidRule;
import net.loyintean.pearlshell.validation.IValidRuleConfig;

/** TODO 不要限制入参为String
 * 
 * @author：jun.lin@yeepay.com
 * @since：2015年1月2日 下午11:21:05
 * @version: */
class StringGreaterThanNumberValidRuleImpl implements IValidRule {

	/** 创建一个新的实例 StringGreaterThanNumberValidRuleImpl. */
	StringGreaterThanNumberValidRuleImpl() {
		super();
	}

	/** @see net.loyintean.pearlshell.validation.
	 *      IValidRule#errorMsg(net.loyintean.pearlshell.validation.IValidRuleConfig) */
	@Override
	public String errorMsg(IValidRuleConfig config) {

		StringBuilder resultBuilder = new StringBuilder(errorMsgPrefix());

		if (config.validParam().length > 1 && config.validParam()[1] != null
				&& (Boolean) config.validParam()[1]) {
			resultBuilder.append("或者等于");
		}

		resultBuilder.append(config.validParam()[0]);

		return resultBuilder.toString();
	}

	/** prefix of {@link #errorMsg(IValidRuleConfig)} @return */
	protected String errorMsgPrefix() {
		return "必须大于";
	}

	/** 将待校验数据，与配置参数中的第0个数值进行比较，检查比较结果
	 * <p>
	 * 如果待校验数据大于配置数值，则校验通过<br>
	 * 如果待校验数据小于配置数值，则校验不通过<br>
	 * 如果两个数值相等，则检查第1个配置数据：如果该数据为true，则校验通过；否则校验不通过。
	 * 
	 * @see net.loyintean.pearlshell.validation.IValidRule#valid(java.lang.Object,
	 *      net.loyintean.pearlshell.validation.IValidRuleConfig) */
	@Override
	public boolean valid(Object toValid, IValidRuleConfig config) {

		isValidParamIllegal(config);

		boolean result = true;

		if (toValid != null) {

			try {
				BigDecimal toValidNum = BigDecimalUtil.toBigDecimal(toValid);

				BigDecimal toCompare = BigDecimalUtil.toBigDecimal(config
						.validParam()[0]);

				result = checkResult(toValidNum.compareTo(toCompare), config);

			} catch (Exception e) {
				throw new IllegalArgumentException("请检查比较双方的数字：" + toValid
						+ " 和 " + config);
			}
		}

		return result;
	}

	/** chech the result of compare for {@link #valid(Object, IValidRuleConfig)}
	 * 
	 * @param compareResult
	 * @param config
	 * @return true for valid success, false for fail. */
	protected boolean checkResult(int compareResult, IValidRuleConfig config) {

		boolean result = true;

		// 或者调整一下if-else的执行顺序
		if (compareResult != 0) {

			// 大于0时，表明第一个数字大于第二个数字
			result = (compareResult > 0);

		} else {

			result = (config.validParam().length <= 1 || config.validParam()[1] == null) ? (false)
					: (Boolean) config.validParam()[1];
		}
		return result;
	}

	/** 配置中的校验参数至少要有一个
	 * <p>
	 * 第一个是用来做比较的数值。建议使用Sring类型，以保持比较精度。<br>
	 * 如果有第二个，必须是布尔类型的，表示是否允许“等于”的比较结果；如果没有，则默认为"fasle"
	 * 
	 * @see net.loyintean.pearlshell.validation.rule.
	 *      INeedAdditionConfig#isValidParamIllegal(net.loyintean.pearlshell.validation.IValidRuleConfig) */
	private void isValidParamIllegal(IValidRuleConfig config)
			throws IllegalArgumentException {

		// 配置中的校验参数至少要有两个
		if (config != null && config.validParam() != null
				&& config.validParam().length > 0) {
			// 尝试各种数字类型
			Object numAtLeast = config.validParam()[0];
			try {

				BigDecimalUtil.toBigDecimal(numAtLeast);
			} catch (Exception e) {
				throw new IllegalArgumentException("请提供一个合法数值");
			}

			if (config.validParam().length > 1
					&& config.validParam()[1] != null) {
				Object isEqualsAllow = config.validParam()[1];

				if (!(isEqualsAllow instanceof Boolean)) {
					throw new IllegalArgumentException(
							"请提供一个布尔类型的配置数据，以声明是否允许两个数值相等。或者不指定该配置数据（不指定时将默认为不允许相等）");
				}
			}

		} else {
			throw new IllegalArgumentException("请提供一个用来比较的数值");
		}

	}

}
